<template>
  <Drawer
    placement="right"
    :closable="true"
    v-model="visible"
    width="400"
    scrollable
    @on-close="cancel"
  >
    <template #header>
      <div class="flex flex-col justify-between">
        <div class="flex items-center mb-4 gap-x-2">
          <img
            src="~@/assets/images/icon_LLM.png"
            class="w-6 h-6"
            alt="Start icon"
          />
          <div class="flex flex-col gap-y-1">
            <p class="text-lg font-semibold text-black">{{ title }}</p>
          </div>
        </div>
        <div class="text-sm text-gray-500">
          调用大语言模型,使用变量和提示词生成回复
        </div>
      </div>
    </template>
    <TypeTab
      v-model="form.issingle"
      :data="DEFAULT_LLM_TABS"
      active-color="#4d53e8"
      bg-color="#efefef"
    />
    <CommonCollapse
      title="模型"
      tip="向模型提供用户指令，如查询或任何基于文本输入的提问。"
    >
      <div class="flex items-center">
        <Select v-model="form.selectmodel">
          <Option v-for="item in modelList" :key="item.id" :value="item.id">{{
            item.name
          }}</Option>
        </Select>
        <Icon class="ml-2" type="md-settings" size="20" />
      </div>
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      v-show="form.issingle == 'batch'"
      title="批处理"
      tip="批处理模式下节点会多次运行，在每一次运行中，批处理列表将按照顺序将列表中的一项赋值给批处理变量，直到达到批处理上限或列表最大长度"
    >
      <template #right>
        <Button
          type="primary"
          size="small"
          icon="md-add"
          @click="addInput('batchjsonlist')"
        ></Button>
      </template>
      <div class="panel-table">
        <div class="panel-table-header">
          <div class="name" style="width: 150px">变量名</div>
          <div class="name">变量值</div>
        </div>
        <div class="panel-table-list">
          <Form ref="formEl" :model="form" label-position="top">
            <div
              class="flex items-center mb-4"
              v-for="(item, index) in form.batchjsonlist"
            >
              <div class="panel-table-item" style="width: 160px">
                <FormItem
                  :key="index"
                  :prop="'batchjsonlist.' + index + '.varname'"
                  :rules="{
                    required: true,
                    message: '变量名不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    v-model="item.varname"
                    placeholder="输入变量名"
                    size="small"
                  />
                </FormItem>
              </div>
              <div
                class="panel-table-item"
                style="width: 100px; margin-right: 0"
              >
                <FormItem>
                  <Select size="small" v-model="item.vartype">
                    <Option
                      v-for="item in BE_TYPE_LIST"
                      :value="item.value"
                      :key="item.value"
                      >{{ item.label }}</Option
                    >
                  </Select>
                </FormItem>
              </div>
              <div class="panel-table-item" style="width: 180px">
                <FormItem
                  :prop="'batchjsonlist.' + index + '.varparam'"
                  :rules="{
                    required: true,
                    message: '变量值不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    size="small"
                    v-model="item.varparam"
                    check-strictly
                    placeholder="输入参数值"
                  >
                  </Input>
                </FormItem>
              </div>
              <div
                class="panel-table-item btn"
                @click="removeInput('batchjsonlist', index)"
              >
                <Icon type="md-remove" />
              </div>
            </div>
          </Form>
        </div>
      </div>
    </CommonCollapse>
    <Divider v-show="form.issingle == 'batch'"></Divider>
    <CommonCollapse title="技能">
      <template #right>
        <Button
          type="primary"
          size="small"
          icon="md-add"
          @click="showModal = true"
        ></Button>
      </template>
      <div
        v-for="item in form.skillJsonlist"
        class="flex p-2 mb-2 border border-solid rounded-xl border-slate-200"
      >
        <div class="flex-1 overflow-hidden">
          <p class="mb-1">{{ item.name }}</p>
          <p class="w-full text-xs truncate text-slate-400">
            {{ item.description }}
          </p>
        </div>
        <div class="flex items-center justify-between w-1/4">
          <Icon
            type="md-copy"
            size="20"
            class="cursor-pointer"
            @click="onCopy(item)"
          />
          <Icon
            type="md-settings"
            size="20"
            class="cursor-pointer"
            @click="onSkillSelect(item)"
          />
          <Icon
            type="ios-trash"
            size="20"
            class="cursor-pointer"
            @click="onUnselect(item)"
          />
        </div>
      </div>
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      title="输入"
      tip="输入需要添加到提示词的信息，这些信息可以被下方的提示词引用"
    >
      <template #right>
        <Button
          type="primary"
          size="small"
          icon="md-add"
          @click="addInput('inoutlist')"
        ></Button>
      </template>
      <div class="panel-table">
        <div class="panel-table-header">
          <div class="name" style="width: 150px">变量名</div>
          <div class="name">变量值</div>
        </div>
        <div class="panel-table-list">
          <Form ref="formEl" :model="form" label-position="top">
            <div
              class="flex items-center mb-4"
              v-for="(item, index) in form.inoutlist"
            >
              <div class="panel-table-item" style="width: 160px">
                <FormItem
                  :key="index"
                  :prop="'inoutlist.' + index + '.varname'"
                  :rules="{
                    required: true,
                    message: '变量名不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    v-model="item.varname"
                    placeholder="输入变量名"
                    size="small"
                  />
                </FormItem>
              </div>
              <div
                class="panel-table-item"
                style="width: 100px; margin-right: 0"
              >
                <FormItem>
                  <Select size="small" v-model="item.vartype">
                    <Option
                      v-for="item in BE_TYPE_LIST"
                      :value="item.value"
                      :key="item.value"
                      >{{ item.label }}</Option
                    >
                  </Select>
                </FormItem>
              </div>
              <div class="panel-table-item" style="width: 180px">
                <FormItem
                  :prop="'inoutlist.' + index + '.varparam'"
                  :rules="{
                    required: true,
                    message: '变量值不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    size="small"
                    v-model="item.varparam"
                    check-strictly
                    placeholder="输入参数值"
                  >
                  </Input>
                </FormItem>
              </div>
              <div
                class="panel-table-item btn"
                @click="removeInput('inoutlist', index)"
              >
                <Icon type="md-remove" />
              </div>
            </div>
          </Form>
        </div>
      </div>
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      title="视觉理解输入"
      tip="用于视觉理解的输入，传入图片or视频的url，并在Prompt中引用该输入，举例：“图片{{变量名}}中有什么？”"
    >
      <template #right>
        <Button
          type="primary"
          size="small"
          icon="md-add"
          @click="addInput('visualjsonlist')"
        ></Button>
      </template>
      <div class="panel-table">
        <div class="panel-table-header">
          <div class="name" style="width: 150px">变量名</div>
          <div class="name">变量值</div>
        </div>
        <div class="panel-table-list">
          <Form ref="formEl" :model="form" label-position="top">
            <div
              class="flex items-center mb-4"
              v-for="(item, index) in form.visualjsonlist"
            >
              <div class="panel-table-item" style="width: 140px">
                <FormItem
                  :key="index"
                  :prop="'visualjsonlist.' + index + '.varname'"
                  :rules="{
                    required: true,
                    message: '变量名不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    v-model="item.varname"
                    placeholder="输入变量名"
                    size="small"
                  />
                </FormItem>
              </div>
              <div class="panel-table-item" style="width: 180px;height: 24px;">
                <!-- <FormItem
                > -->
                  <InputUpload v-model="item.vardesc" :nodeID="id" />
                <!-- </FormItem> -->
              </div>
              <div
                class="panel-table-item btn"
                @click="removeInput('visualjsonlist', index)"
              >
                <Icon type="md-remove" />
              </div>
            </div>
          </Form>
        </div>
      </div>
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      title="系统提示词"
      tip="为对话提供系统级指导，如设定人设和回复逻辑。"
    >
      <Input
        v-model="form.systempromptword"
        type="textarea"
        :rows="4"
        placeholder="系统提示词，可以使用{{变量名}}、{{变量名.子变量名}}、{{变量名[数组索引]}}的方式引用输入参数中的变量"
      />
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      title="用户提示词"
      tip="向模型提供用户指令，如查询或任何基于文本输入的提问。"
    >
      <Input
        v-model="form.userpromptword"
        type="textarea"
        :rows="4"
        placeholder="用户提示词，可以使用{{变量名}}、{{变量名.子变量名}}、{{变量名[数组索引]}}的方式引用输入参数中的变量"
      />
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse title="输出" tip="大模型运行完成后生成的内容">
      <template #right>
        <!-- <Select
          v-model="form.outputFormat"
          style="width: 160px"
          size="small"
          transfer
        >
          <Option
            v-for="item in OUTPUT_FORMAT_OPTIONS"
            :value="item.value"
            :key="item.value"
            >{{ item.label }}</Option
          >
        </Select> -->
        <Button
          v-show="form.outputFormat == 'JSON'"
          type="primary"
          size="small"
          icon="md-exit"
          class="mx-1"
          @click="addInput('outputjsonlist')"
        ></Button>
        <Button
          type="primary"
          size="small"
          icon="md-add"
          @click="addInput('outputjsonlist')"
        ></Button>
      </template>
      <div class="panel-table">
        <div class="panel-table-header">
          <div class="name" style="width: 170px">变量名</div>
          <div class="name">变量类型</div>
        </div>
        <div class="panel-table-list">
          <Form ref="formEl" :model="form" label-position="top">
            <div
              class="flex items-center mb-4"
              v-for="(item, index) in form.outputjsonlist"
            >
              <div class="panel-table-item" style="width: 180px">
                <FormItem
                  :key="index"
                  :prop="'outputjsonlist.' + index + '.varname'"
                  :rules="{
                    required: true,
                    message: '变量名不可为空',
                    trigger: 'blur',
                  }"
                >
                  <Input
                    v-model="item.varname"
                    placeholder="输入变量名"
                    size="small"
                    show-word-limit
                    maxlength="20"
                  />
                </FormItem>
              </div>
              <div class="panel-table-item" style="width: 180px">
                <FormItem>
                  <Select size="small" v-model="item.vartype">
                    <Option
                      v-for="item in BE_TYPE_LIST"
                      :value="item.value"
                      :key="item.value"
                      >{{ item.label }}</Option
                    >
                  </Select>
                </FormItem>
              </div>
              <div class="panel-table-item btn">
                <Icon type="md-resize" />
              </div>
              <div
                class="panel-table-item btn"
                :class="{ disabled: index == 0 }"
                @click="removeInput('outputjsonlist', index)"
              >
                <Icon type="md-remove" />
              </div>
            </div>
          </Form>
        </div>
        <div class="flex items-center">
          <span class="text-sm">reasoning_content</span>
          <Tooltip
            transfer
            theme="light"
            placement="top"
            max-width="400"
            content="推理内容，支持输出思维链的模型特有"
          >
            <Icon type="ios-alert-outline" class="mx-2" size="16" />
          </Tooltip>
          <div class="text-bg-normal">String</div>
        </div>
      </div>
    </CommonCollapse>
    <Divider></Divider>
    <CommonCollapse
      title="异常处理"
      tip="可设置异常处理，包括超时、重试、异常处理方式。"
    >
      <CommonAbnormalModule :form="form.excepjsondata" />
    </CommonCollapse>
  </Drawer>
  <!-- 选择技能 -->
  <Modal v-model="showModal" footer-hide width="70vw">
    <template #header>
      <div class="flex text-lg">
        <div
          v-for="(type, i) in DEFAULT_SKILL_TYPE"
          :key="i"
          class="px-3 border-solid cursor-pointer border-slate-300"
          :class="{
            'border-r': i < DEFAULT_SKILL_TYPE.length - 1,
            'text-blue-600 font-bold': i == selectType,
          }"
          @click="onSelectType(i)"
        >
          {{ type.name }}
        </div>
      </div>
    </template>
    <div class="flex overflow-hidden" style="height: 60vh">
      <div class="w-1/4 h-full p-4 bg-slate-100">
        <Input class="mb-3" search placeholder="搜索" />
        <!-- <Dropdown class="w-full" transfer>
          <Button type="primary" class="w-full">
            新建数据表
            <Icon type="ios-arrow-down"></Icon>
          </Button>
        </Dropdown>
        <p
          class="p-2 mt-4 text-sm text-black rounded cursor-pointer bg-slate-200"
        >
          <Icon type="ios-paper" />资源库数据库
        </p> -->
      </div>
      <div class="w-3/4 h-full p-6 overflow-auto">
        <div
          class="flex items-center justify-between w-full pb-2 mb-2 border-b border-solid cursor-pointer border-slate-200"
          v-for="item in skillList"
          :key="item.id"
        >
          <div class="flex items-center flex-1 ml-3">
            <!-- <img
              class="w-8 h-8 rounded"
              src="~@/assets/images/database_default.png"
              alt="database default"
            /> -->
            <div class="flex-1">
              <p class="font-bold">{{ item.name }}</p>
              <p class="mt-1 text-xs text-slate-500">{{ item.description }}</p>
              <p
                class="mt-1 text-xs text-slate-400"
                v-if="item.releasedate || item.createtime"
              >
                发布于{{
                  formatToDateTime(item.releasedate || item.createtime)
                }}
              </p>
            </div>
          </div>
          <Button
            v-if="selectSkills.includes(item.name)"
            size="small"
            ghost
            type="error"
            @click="onUnselect(item)"
            >移除</Button
          >

          <Button v-else size="small" @click="onSelect(item)">添加</Button>
        </div>
      </div>
    </div>
  </Modal>
  <!-- 技能配置参数 -->
  <Modal v-model="showSetting" title="设置" width="800px">
    <div class="flex overflow-hidden" style="height: 60vh">
      <Tabs value="name1" type="card">
        <TabPane label="配置输入参数" name="name1">
          <el-table :data="selectSkill?.configinlist" style="width: 100%">
            <el-table-column label="参数名称" prop="name" min-width="400px">
              <template #default="{ row }">
                <div>
                  <div>
                    <span class="pr-2">{{ row.name }}</span>
                    <Tag color="default">{{ row.datatype }}</Tag>
                    <Tag color="red" v-if="row.isrequired">必填</Tag>
                  </div>
                  <p class="text-sm text-slate-400">{{ row.description }}</p>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="默认值" prop="defvalue" min-width="200px">
              <template #default="{ row }">
                <Input
                  v-model="row.defvalue"
                  size="small"
                  placeholder=""
                  show-word-limit
                  maxlength="300"
                ></Input>
              </template>
            </el-table-column>
            <el-table-column label="开启" prop="isopen">
              <template #default="{ row }">
                <Switch v-model="row.isopen" size="small" />
              </template>
            </el-table-column>
          </el-table>
        </TabPane>
        <TabPane label="配置输出参数" name="name2">
          <el-table :data="selectSkill?.configoutlist" style="width: 100%">
            <el-table-column label="参数名称" prop="name" min-width="400px">
              <template #default="{ row }">
                <div>
                  <div>
                    <span class="pr-2">{{ row.name }}</span>
                    <Tag color="default">{{ row.datatype }}</Tag>
                    <Tag color="red" v-if="row.isrequired">必填</Tag>
                  </div>
                  <p class="text-sm text-slate-400">{{ row.description }}</p>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="默认值" prop="defvalue" min-width="200px">
              <template #default="{ row }">
                <Input
                  v-model="row.defvalue"
                  size="small"
                  placeholder=""
                  show-word-limit
                  maxlength="300"
                ></Input>
              </template>
            </el-table-column>
            <el-table-column label="开启" prop="isopen">
              <template #default="{ row }">
                <Switch v-model="row.isopen" size="small" />
              </template>
            </el-table-column>
          </el-table>
        </TabPane>
      </Tabs>
    </div>
    <template #footer>
      <Button type="primary" @click="onSkillSave">保存</Button>
    </template>
  </Modal>
</template>
<script setup>
import { ref } from 'vue';
import { flowStore } from '@/store/flow';
import { Message } from 'view-ui-plus';

import CommonCollapse from '@/components/CommonCollapse/index.vue';
import CommonAbnormalModule from './common-abnormal-module.vue';
import InputUpload from '../input-upload.vue';

import { listPlugin } from '@/api/modules/flow';
import { agentList } from '@/api/modules/agent';
import { myKnowledge } from '@/api/modules/knowledgeBase';

import { formatToDateTime } from '@/util/dateUtil';
import { BE_TYPE_LIST } from '../../lib/constant';

const DEFAULT_LLM_TABS = [
  {
    label: '单次',
    value: 'single',
  },
  {
    label: '批处理',
    value: 'batch',
  },
];
const OUTPUT_FORMAT_OPTIONS = [
  {
    label: '输出格式文本',
    value: 'text',
  },
  {
    label: '输出格式Markdown',
    value: 'markdown',
  },
  {
    label: '输出格式JSON',
    value: 'JSON',
  },
];

const DEFAULT_SKILL_TYPE = [
  {
    name: '工具',
    api: listPlugin,
    data: {
      data: {}
    },
  },
  {
    name: '工作流',
    api: agentList,
    data: {
      query: {
        p: 1,
        ps: 1000,
      },
      data: {
        aitype: 'all',
      },
    },
  },
  {
    name: '知识库',
    api: myKnowledge.catePage,
    data: {
      query: {
        p: 1,
        ps: 1000,
      },
      data: {
        aitype: 'kb',
      },
    },
  },
];

const props = defineProps({
  form: {
    type: Object,
    default: () => {},
  },
  title: {
    type: String,
    default: '输出',
  },
  id: {
    type: String,
    default: ''
  }
});

const emit = defineEmits(['add', 'remove', 'cancel']);
const { modelList } = flowStore();

const visible = ref(false);
// 弹窗显示
const showModal = ref(false);
const showSetting = ref(false);
// 技能列表
const skillList = ref([]);
const selectSkills = ref([]);
const selectType = ref(0);
const selectSkill = ref();

const getList = async () => {
  const type = DEFAULT_SKILL_TYPE[selectType.value];
  const { data } = await type.api({ ...type.data });
  skillList.value = selectType.value == 0 ? data : data.topicList;
};
getList();

const onSelectType = (i) => {
  if (selectType.value == i) return;
  selectType.value = i;
  getList();
};

const onSelect = (item) => {
  props.form.skillJsonlist.push({
    name: item.name,
    description: item.description,
    configinlist: item.configinlist,
    configoutlist: item.configoutlist,
  });
  selectSkills.value.push(item.name);
  showModal.value = false;
};

const onUnselect = (item) => {
  const index = selectSkills.value.indexOf(item.name);
  selectSkills.value.splice(index, 1);
  props.form.skillJsonlist.splice(index, 1);
};

const onSkillSelect = (item) => {
  selectSkill.value = item;
  showSetting.value = true;
};

const onSkillSave = () => {
  const index = selectSkills.value.indexOf(selectSkill.value.name);
  props.form.skillJsonlist[index].configinlist = selectSkill.value.configinlist;
  props.form.skillJsonlist[index].configoutlist = selectSkill.value.configoutlist;
  showSetting.value = false;
};

const onCopy = async (item) => {
  try {
    await navigator.clipboard.writeText(item.name);
    Message.success('已复制');
  } catch (err) {
    Message.error(err);
  }
};

// 组件的增删
const addInput = (listKey) => {
  emit('add', listKey);
};
const removeInput = (listKey, index) => {
  if (listKey == 'outputjsonlist' && index == 0) return;
  emit('remove', listKey, index);
};
const init = () => {
  visible.value = true;
};
const cancel = () => {
  visible.value = false;
  emit('cancel');
};

defineExpose({
  init,
});
</script>
<style lang="scss" scoped>
.panel-table-header {
  align-items: center;
  display: flex;
  gap: 4px;
  padding: 0 4px;

  .name {
    width: 120px;
    margin-right: 6px;
    box-sizing: content-box;
  }
  .center {
    text-align: center;
  }
}

:deep(.ivu-form-item-error-tip){
  font-size: 12px;
}
.panel-table-item {
  height: 30px;
  margin-right: 6px;
  &.center {
    text-align: center;
  }
  &.btn {
    cursor: pointer;
    font-size: 16px;
    font-weight: bold;
    margin-left: 12px;
    height: 22px;
  }
}

</style>
